package com.gitee.wsl.collections.deque

import com.gitee.wsl.collections.api.SequencedCollection
import com.gitee.wsl.collections.queue.Queue


/**
 * A linear collection that supports element insertion and removal at
 * both ends.  The name *deque* is short for "double ended queue"
 * and is usually pronounced "deck".  Most `Deque`
 * implementations place no fixed limits on the number of elements
 * they may contain, but this interface supports capacity-restricted
 * deques as well as those with no fixed size limit.
 *
 *
 * This interface defines methods to access the elements at both
 * ends of the deque.  Methods are provided to insert, remove, and
 * examine the element.  Each of these methods exists in two forms:
 * one throws an exception if the operation fails, the other returns a
 * special value (either `null` or `false`, depending on
 * the operation).  The latter form of the insert operation is
 * designed specifically for use with capacity-restricted
 * `Deque` implementations; in most implementations, insert
 * operations cannot fail.
 *
 *
 * The twelve methods described above are summarized in the
 * following table:
 *
 * <table class="striped">
 * <caption>Summary of Deque methods</caption>
 * <thead>
 * <tr>
 * <td rowspan="2"></td>
 * <th scope="col" colspan="2"> First Element (Head)</th>
 * <th scope="col" colspan="2"> Last Element (Tail)</th>
</tr> *
 * <tr>
 * <th scope="col" style="font-weight:normal; font-style:italic">Throws exception</th>
 * <th scope="col" style="font-weight:normal; font-style:italic">Special value</th>
 * <th scope="col" style="font-weight:normal; font-style:italic">Throws exception</th>
 * <th scope="col" style="font-weight:normal; font-style:italic">Special value</th>
</tr> *
</thead> *
 * <tbody>
 * <tr>
 * <th scope="row">Insert</th>
 * <td>[addFirst(e)][.addFirst]</td>
 * <td>[offerFirst(e)][.offerFirst]</td>
 * <td>[addLast(e)][.addLast]</td>
 * <td>[offerLast(e)][.offerLast]</td>
</tr> *
 * <tr>
 * <th scope="row">Remove</th>
 * <td>[removeFirst()][.removeFirst]</td>
 * <td>[pollFirst()][.pollFirst]</td>
 * <td>[removeLast()][.removeLast]</td>
 * <td>[pollLast()][.pollLast]</td>
</tr> *
 * <tr>
 * <th scope="row">Examine</th>
 * <td>[getFirst()][.getFirst]</td>
 * <td>[peekFirst()][.peekFirst]</td>
 * <td>[getLast()][.getLast]</td>
 * <td>[peekLast()][.peekLast]</td>
</tr> *
</tbody> *
</table> *
 *
 *
 * This interface extends the [Queue] interface.  When a deque is
 * used as a queue, FIFO (First-In-First-Out) behavior results.  Elements are
 * added at the end of the deque and removed from the beginning.  The methods
 * inherited from the `Queue` interface are precisely equivalent to
 * `Deque` methods as indicated in the following table:
 *
 * <table class="striped">
 * <caption>Comparison of Queue and Deque methods</caption>
 * <thead>
 * <tr>
 * <th scope="col"> `Queue` Method</th>
 * <th scope="col"> Equivalent `Deque` Method</th>
</tr> *
</thead> *
 * <tbody>
 * <tr>
 * <th scope="row">[add(e)][.add]</th>
 * <td>[addLast(e)][.addLast]</td>
</tr> *
 * <tr>
 * <th scope="row">[offer(e)][.offer]</th>
 * <td>[offerLast(e)][.offerLast]</td>
</tr> *
 * <tr>
 * <th scope="row">[remove()][.remove]</th>
 * <td>[removeFirst()][.removeFirst]</td>
</tr> *
 * <tr>
 * <th scope="row">[poll()][.poll]</th>
 * <td>[pollFirst()][.pollFirst]</td>
</tr> *
 * <tr>
 * <th scope="row">[element()][.element]</th>
 * <td>[getFirst()][.getFirst]</td>
</tr> *
 * <tr>
 * <th scope="row">[peek()][.peek]</th>
 * <td>[peekFirst()][.peekFirst]</td>
</tr> *
</tbody> *
</table> *
 *
 *
 * Deques can also be used as LIFO (Last-In-First-Out) stacks.  This
 * interface should be used in preference to the legacy [Stack] class.
 * When a deque is used as a stack, elements are pushed and popped from the
 * beginning of the deque.  Stack methods are equivalent to `Deque`
 * methods as indicated in the table below:
 *
 * <table class="striped">
 * <caption>Comparison of Stack and Deque methods</caption>
 * <thead>
 * <tr>
 * <th scope="col"> Stack Method</th>
 * <th scope="col"> Equivalent `Deque` Method</th>
</tr> *
</thead> *
 * <tbody>
 * <tr>
 * <th scope="row">[push(e)][.push]</th>
 * <td>[addFirst(e)][.addFirst]</td>
</tr> *
 * <tr>
 * <th scope="row">[pop()][.pop]</th>
 * <td>[removeFirst()][.removeFirst]</td>
</tr> *
 * <tr>
 * <th scope="row">[peek()][.peek]</th>
 * <td>[peekFirst()][.peekFirst]</td>
</tr> *
</tbody> *
</table> *
 *
 *
 * Note that the [peek][.peek] method works equally well when
 * a deque is used as a queue or a stack; in either case, elements are
 * drawn from the beginning of the deque.
 *
 *
 * This interface provides two methods to remove interior
 * elements, [removeFirstOccurrence][.removeFirstOccurrence] and
 * [removeLastOccurrence][.removeLastOccurrence].
 *
 *
 * Unlike the [List] interface, this interface does not
 * provide support for indexed access to elements.
 *
 *
 * While `Deque` implementations are not strictly required
 * to prohibit the insertion of null elements, they are strongly
 * encouraged to do so.  Users of any `Deque` implementations
 * that do allow null elements are strongly encouraged *not* to
 * take advantage of the ability to insert nulls.  This is so because
 * `null` is used as a special return value by various methods
 * to indicate that the deque is empty.
 *
 *
 * `Deque` implementations generally do not define
 * element-based versions of the `equals` and `hashCode`
 * methods, but instead inherit the identity-based versions from class
 * `Object`.
 *
 *
 * This interface is a member of the
 * [
 * Java Collections Framework]({@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework).
 *
 * @author Doug Lea
 * @author Josh Bloch
 * @since  1.6
 * @param <E> the type of elements held in this deque
</E> */
interface Deque<E> : Queue<E>, SequencedCollection<E> {
    /**
     * Inserts the specified element at the front of this deque if it is
     * possible to do so immediately without violating capacity restrictions,
     * throwing an `IllegalStateException` if no space is currently
     * available.  When using a capacity-restricted deque, it is generally
     * preferable to use method [.offerFirst].
     *
     * @param e the element to add
     * @throws IllegalStateException if the element cannot be added at this
     * time due to capacity restrictions
     * @throws ClassCastException if the class of the specified element
     * prevents it from being added to this deque
     * @throws NullPointerException if the specified element is null and this
     * deque does not permit null elements
     * @throws IllegalArgumentException if some property of the specified
     * element prevents it from being added to this deque
     */
    override fun addFirst(e: E)

    /**
     * Inserts the specified element at the end of this deque if it is
     * possible to do so immediately without violating capacity restrictions,
     * throwing an `IllegalStateException` if no space is currently
     * available.  When using a capacity-restricted deque, it is generally
     * preferable to use method [.offerLast].
     *
     *
     * This method is equivalent to [.add].
     *
     * @param e the element to add
     * @throws IllegalStateException if the element cannot be added at this
     * time due to capacity restrictions
     * @throws ClassCastException if the class of the specified element
     * prevents it from being added to this deque
     * @throws NullPointerException if the specified element is null and this
     * deque does not permit null elements
     * @throws IllegalArgumentException if some property of the specified
     * element prevents it from being added to this deque
     */
    override fun addLast(e: E)

    /**
     * Inserts the specified element at the front of this deque unless it would
     * violate capacity restrictions.  When using a capacity-restricted deque,
     * this method is generally preferable to the [.addFirst] method,
     * which can fail to insert an element only by throwing an exception.
     *
     * @param e the element to add
     * @return `true` if the element was added to this deque, else
     * `false`
     * @throws ClassCastException if the class of the specified element
     * prevents it from being added to this deque
     * @throws NullPointerException if the specified element is null and this
     * deque does not permit null elements
     * @throws IllegalArgumentException if some property of the specified
     * element prevents it from being added to this deque
     */
    fun offerFirst(e: E): Boolean

    /**
     * Inserts the specified element at the end of this deque unless it would
     * violate capacity restrictions.  When using a capacity-restricted deque,
     * this method is generally preferable to the [.addLast] method,
     * which can fail to insert an element only by throwing an exception.
     *
     * @param e the element to add
     * @return `true` if the element was added to this deque, else
     * `false`
     * @throws ClassCastException if the class of the specified element
     * prevents it from being added to this deque
     * @throws NullPointerException if the specified element is null and this
     * deque does not permit null elements
     * @throws IllegalArgumentException if some property of the specified
     * element prevents it from being added to this deque
     */
    fun offerLast(e: E): Boolean

    /**
     * Retrieves and removes the first element of this deque.  This method
     * differs from [pollFirst][.pollFirst] only in that it throws an
     * exception if this deque is empty.
     *
     * @return the head of this deque
     * @throws NoSuchElementException if this deque is empty
     */
    override fun removeFirst(): E

    /**
     * Retrieves and removes the last element of this deque.  This method
     * differs from [pollLast][.pollLast] only in that it throws an
     * exception if this deque is empty.
     *
     * @return the tail of this deque
     * @throws NoSuchElementException if this deque is empty
     */
    override fun removeLast(): E

    /**
     * Retrieves and removes the first element of this deque,
     * or returns `null` if this deque is empty.
     *
     * @return the head of this deque, or `null` if this deque is empty
     */
    fun pollFirst(): E?

    /**
     * Retrieves and removes the last element of this deque,
     * or returns `null` if this deque is empty.
     *
     * @return the tail of this deque, or `null` if this deque is empty
     */
    fun pollLast(): E?

    /**
     * Retrieves, but does not remove, the first element of this deque.
     *
     * This method differs from [peekFirst][.peekFirst] only in that it
     * throws an exception if this deque is empty.
     *
     * @return the head of this deque
     * @throws NoSuchElementException if this deque is empty
     */
    //override fun getFirst(): E

    /**
     * Retrieves, but does not remove, the last element of this deque.
     * This method differs from [peekLast][.peekLast] only in that it
     * throws an exception if this deque is empty.
     *
     * @return the tail of this deque
     * @throws NoSuchElementException if this deque is empty
     */
    //override fun getLast(): E?

    /**
     * Retrieves, but does not remove, the first element of this deque,
     * or returns `null` if this deque is empty.
     *
     * @return the head of this deque, or `null` if this deque is empty
     */
    fun peekFirst(): E?

    /**
     * Retrieves, but does not remove, the last element of this deque,
     * or returns `null` if this deque is empty.
     *
     * @return the tail of this deque, or `null` if this deque is empty
     */
    fun peekLast(): E?

    /**
     * Removes the first occurrence of the specified element from this deque.
     * If the deque does not contain the element, it is unchanged.
     * More formally, removes the first element `e` such that
     * `Objects.equals(o, e)` (if such an element exists).
     * Returns `true` if this deque contained the specified element
     * (or equivalently, if this deque changed as a result of the call).
     *
     * @param o element to be removed from this deque, if present
     * @return `true` if an element was removed as a result of this call
     * @throws ClassCastException if the class of the specified element
     * is incompatible with this deque
     * ([-restrictions optional][Collection])
     * @throws NullPointerException if the specified element is null and this
     * deque does not permit null elements
     * ([-restrictions optional][Collection])
     */
    fun removeFirstOccurrence(o: E): Boolean

    /**
     * Removes the last occurrence of the specified element from this deque.
     * If the deque does not contain the element, it is unchanged.
     * More formally, removes the last element `e` such that
     * `Objects.equals(o, e)` (if such an element exists).
     * Returns `true` if this deque contained the specified element
     * (or equivalently, if this deque changed as a result of the call).
     *
     * @param o element to be removed from this deque, if present
     * @return `true` if an element was removed as a result of this call
     * @throws ClassCastException if the class of the specified element
     * is incompatible with this deque
     * ([-restrictions optional][Collection])
     * @throws NullPointerException if the specified element is null and this
     * deque does not permit null elements
     * ([-restrictions optional][Collection])
     */
    fun removeLastOccurrence(o: E): Boolean


    // *** Stack methods ***
    /**
     * Pushes an element onto the stack represented by this deque (in other
     * words, at the head of this deque) if it is possible to do so
     * immediately without violating capacity restrictions, throwing an
     * `IllegalStateException` if no space is currently available.
     *
     *
     * This method is equivalent to [.addFirst].
     *
     * @param e the element to push
     * @throws IllegalStateException if the element cannot be added at this
     * time due to capacity restrictions
     * @throws ClassCastException if the class of the specified element
     * prevents it from being added to this deque
     * @throws NullPointerException if the specified element is null and this
     * deque does not permit null elements
     * @throws IllegalArgumentException if some property of the specified
     * element prevents it from being added to this deque
     */
    fun push(e: E)

    /**
     * Pops an element from the stack represented by this deque.  In other
     * words, removes and returns the first element of this deque.
     *
     *
     * This method is equivalent to [.removeFirst].
     *
     * @return the element at the front of this deque (which is the top
     * of the stack represented by this deque)
     * @throws NoSuchElementException if this deque is empty
     */
    fun pop(): E?


    /**
     * Returns an iterator over the elements in this deque in proper sequence.
     * The elements will be returned in order from first (head) to last (tail).
     *
     * @return an iterator over the elements in this deque in proper sequence
     */
    override fun iterator(): MutableIterator<E>

    /**
     * Returns an iterator over the elements in this deque in reverse
     * sequential order.  The elements will be returned in order from
     * last (tail) to first (head).
     *
     * @return an iterator over the elements in this deque in reverse
     * sequence
     */
    fun descendingIterator(): MutableIterator<E>

    /**
     * {@inheritDoc}
     *
     * @implSpec
     * The implementation in this interface returns a reverse-ordered Deque
     * view. The `reversed()` method of the view returns a reference
     * to this Deque. Other operations on the view are implemented via calls to
     * public methods on this Deque. The exact relationship between calls on the
     * view and calls on this Deque is unspecified. However, order-sensitive
     * operations generally behave as if they delegate to the appropriate method
     * with the opposite orientation. For example, calling `getFirst` on
     * the view might result in a call to `getLast` on this Deque.
     *
     * @return a reverse-ordered view of this collection, as a `Deque`
     * @since 21
     */
    override fun reversed(): Deque<E> {
        return ReverseOrderDequeView.of(this)
    }


    companion object
}
